package com.gzc.just.play.last.war.sceneserver.benchmark;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import static org.junit.jupiter.api.Assertions.*;

/**
 * 属性计算性能基准测试
 * 
 * 测试目标:
 * - 属性计算: 5,000 ops/sec
 * - 平均延迟: < 200μs
 * - 99% 延迟: < 1000μs
 */
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(value = 1)
public class AttributeCalculatorBenchmark {
    
    private Random random = new Random();
    
    // 基础属性
    private Map<String, Integer> baseAttributes;
    private Map<String, Float> attributeModifiers;
    
    // 缓存系统
    private Map<String, Integer> cachedAttributes = new HashMap<>();
    private boolean cacheValid = false;
    
    @BeforeEach
    public void setup() {
        // 初始化基础属性
        baseAttributes = new HashMap<>();
        baseAttributes.put("strength", 100);
        baseAttributes.put("agility", 80);
        baseAttributes.put("intelligence", 60);
        baseAttributes.put("vitality", 90);
        baseAttributes.put("attackPower", 300);
        baseAttributes.put("defense", 150);
        baseAttributes.put("health", 1000);
        baseAttributes.put("mana", 500);
        
        // 初始化属性修饰符
        attributeModifiers = new HashMap<>();
        attributeModifiers.put("strength", 1.2f);
        attributeModifiers.put("agility", 1.1f);
        attributeModifiers.put("intelligence", 1.15f);
        attributeModifiers.put("vitality", 1.05f);
    }
    
    @Benchmark
    public int benchmarkBasicAttributeCalculation() {
        // 基础属性计算
        return baseAttributes.get("strength") + baseAttributes.get("agility");
    }
    
    @Benchmark
    public int benchmarkAttributeWithModifiers() {
        // 带修饰符的属性计算
        int strength = baseAttributes.get("strength");
        float modifier = attributeModifiers.getOrDefault("strength", 1.0f);
        return (int) (strength * modifier);
    }
    
    @Benchmark
    public int benchmarkCachedAttributeCalculation() {
        // 缓存属性计算
        if (!cacheValid) {
            cachedAttributes.put("totalAttackPower", calculateAttackPower());
            cacheValid = true;
        }
        return cachedAttributes.get("totalAttackPower");
    }
    
    private int calculateAttackPower() {
        return baseAttributes.get("attackPower") + baseAttributes.get("strength") * 2;
    }
    
    @Benchmark
    public void benchmarkInvalidateCache() {
        // 缓存失效
        cacheValid = false;
        cachedAttributes.clear();
    }
    
    @Benchmark
    public Map<String, Integer> benchmarkAllAttributeRecalculation() {
        // 所有属性重新计算
        Map<String, Integer> calculated = new HashMap<>();
        
        for (Map.Entry<String, Integer> entry : baseAttributes.entrySet()) {
            String attr = entry.getKey();
            int baseValue = entry.getValue();
            float modifier = attributeModifiers.getOrDefault(attr, 1.0f);
            calculated.put(attr, (int) (baseValue * modifier));
        }
        
        return calculated;
    }
    
    @Benchmark
    public int benchmarkAttributeDependencyCalculation() {
        // 属性依赖计算（如攻击力依赖力量）
        int strength = baseAttributes.get("strength");
        int agility = baseAttributes.get("agility");
        
        // 复杂属性计算（例如：攻击力 = 基础攻击力 + 力量*0.5 + 敏捷*0.2）
        int attackPower = baseAttributes.get("attackPower") + (int)(strength * 0.5) + (int)(agility * 0.2);
        
        return attackPower;
    }
    
    @Benchmark
    public boolean benchmarkAttributeThresholdCheck() {
        // 属性阈值检查
        int health = baseAttributes.get("health");
        int maxHealth = 1000;
        float healthPercentage = (float) health / maxHealth;
        
        return healthPercentage < 0.2f; // 低于20%血量
    }
    
    @Benchmark
    public int benchmarkRandomAttributeModification() {
        // 随机属性修改（模拟装备属性）
        String[] attributes = {"strength", "agility", "intelligence", "vitality"};
        String attr = attributes[random.nextInt(attributes.length)];
        
        int currentValue = baseAttributes.get(attr);
        int modification = random.nextInt(20) - 10; // -10 到 +10
        
        int newValue = currentValue + modification;
        baseAttributes.put(attr, Math.max(0, newValue));
        
        // 返回修改后的值
        return newValue;
    }
    
    /**
     * JUnit 测试方法 - 验证基准测试是否可以正常工作
     */
    @Test
    public void testAttributeCalculationSetup() {
        // 测试设置是否正确
        assertNotNull(baseAttributes, "Base attributes should not be null");
        assertFalse(baseAttributes.isEmpty(), "Base attributes should not be empty");
        
        // 测试方法可以正常运行
        int result = benchmarkBasicAttributeCalculation();
        assertTrue(result > 0, "Basic attribute calculation should return positive value");
        
        Map<String, Integer> allAttr = benchmarkAllAttributeRecalculation();
        assertFalse(allAttr.isEmpty(), "All attributes calculation should return non-empty map");
        
        // 测试缓存
        cacheValid = false;
        int cachedResult = benchmarkCachedAttributeCalculation();
        assertTrue(cachedResult > 0, "Cached calculation should return positive value");
        
        // 再次调用应该使用缓存
        benchmarkCachedAttributeCalculation();
    }
    
    /**
     * JUnit 测试方法 - 验证基准测试方法的性能
     */
    @Test
    public void testAttributeCalculationPerformance() {
        // 初始化测试数据
        setup();
        
        // 测试基础性能
        long startTime = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            benchmarkBasicAttributeCalculation();
        }
        long duration = System.nanoTime() - startTime;
        
        // 验证在合理时间内完成（1秒内）
        assertTrue(duration < 1_000_000_000L, 
            "Basic attribute calculation should complete within 1 second");
        
        // 测试缓存性能
        cacheValid = false;
        benchmarkCachedAttributeCalculation(); // 初始化缓存
        
        startTime = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            benchmarkCachedAttributeCalculation();
        }
        duration = System.nanoTime() - startTime;
        
        // 验证缓存更快完成（0.5秒内）
        assertTrue(duration < 500_000_000L, 
            "Cached attribute calculation should complete within 0.5 seconds");
    }
}